package com.unicom.xiyan.utils;

import com.alibaba.fastjson.JSON;
import com.unicom.xiyan.entity.LogVo;
import com.unicom.xiyan.entity.User;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author liry
 * @version 1.0
 * @date Created on 2021/3/24 17:01
 * Description:
 */

@Component
public class EsUtil {

    @Resource
    private RestHighLevelClient restHighLevelClient;

    public void testEsConfig() {
        System.out.println(restHighLevelClient);
    }


    // 创建索引， 保存数据
    public void indexData() throws IOException {
        IndexRequest indexRequest = new IndexRequest("posts", "doc", "1");

        User user = new User();

        user.setUsername("kimchy");
        user.setDate(new Date());
        user.setMessage("trying out Elasticsearch");

        String jsonString = JSON.toJSONString(user);
        indexRequest.source(jsonString, XContentType.JSON);


        IndexResponse response = restHighLevelClient.index(indexRequest);

        System.out.println(response);
    }


    // 检索数据
    public void getData() throws IOException {
        GetRequest getRequest = new GetRequest(
                "posts",
                "doc",
                "1");

        GetResponse response = restHighLevelClient.get(getRequest);

        // 获取source并转成string类型
        String sourceAsString = response.getSourceAsString();

        // 解析成JavaBean
        User user = JSON.parseObject(sourceAsString, User.class);

        System.out.println(user);
    }


    // 词条查询
    public void searchData() throws IOException {
        // 指定化索引
        SearchRequest searchRequest = new SearchRequest("uip-edu");
        // 指定类型
        searchRequest.types("logvo");

        SearchSourceBuilder searchRequestBuilder = new SearchSourceBuilder();

        // 根据条件查询： loglevel = INFO
        searchRequestBuilder.query(QueryBuilders.matchQuery("loglevel", "INFO"));

        // 设置分页
        searchRequestBuilder.from(0);
        searchRequestBuilder.size(100);

        // 包装请求信息
        searchRequest.source(searchRequestBuilder);

        // 发送请求
        SearchResponse search = restHighLevelClient.search(searchRequest);

        System.out.println(search);

        SearchHits hits = search.getHits();

        getHitsData(hits);
    }


    // 查询所有数据
    public void queryAllData() throws IOException {
        // 指定化索引
        SearchRequest searchRequest = new SearchRequest("uip-edu");
        // 指定类型
        searchRequest.types("logvo");

        SearchSourceBuilder searchRequestBuilder = new SearchSourceBuilder();

        // 查询所有
        searchRequestBuilder.query(QueryBuilders.matchAllQuery());

        // 设置分页
        searchRequestBuilder.from(0);
        searchRequestBuilder.size(100);

        // 包装请求信息
        searchRequest.source(searchRequestBuilder);

        // 发送请求
        SearchResponse search = restHighLevelClient.search(searchRequest);

        System.out.println(search);

    }

    // 时间范围搜索
    public void rangeData() throws IOException {
        // 指定化索引
        SearchRequest searchRequest = new SearchRequest("uip-edu");

        // 指定类型
        searchRequest.types("logvo");

        SearchSourceBuilder searchRequestBuilder = new SearchSourceBuilder();

        // 范围查询
        // 问题： elasticsearch 在处理 范围查询时，对text类型数据不生效，查询结果的数据不在该范围内
        // 对Date类型数据查询，结果正常
        //  grok 对原始数据分词之后都是text类型，因此在对text类型数据进行范围查询时，需要在被查询字段上添加.keyword
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders
                .rangeQuery("logTimestamp.keyword")
                .from("2021-03-10 21:42:00")
                .to("2021-03-26 21:35:32")
                .format("epoch_millis");
        searchRequestBuilder.query(rangeQueryBuilder);

        // 设置分页
        searchRequestBuilder.from(0);
        searchRequestBuilder.size(100);

        // 包装请求信息
        searchRequest.source(searchRequestBuilder);

        // 发送请求
        SearchResponse search = restHighLevelClient.search(searchRequest);

        SearchHits hits = search.getHits();
        getHitsData(hits);

    }

    private void getHitsData(SearchHits hits) {
        List<LogVo> result = new ArrayList<>();
        hits.forEach(hit -> {

            // 将map 转换为string
            String sourceAsString = hit.getSourceAsString();
            LogVo logVo = JSON.parseObject(sourceAsString, LogVo.class);
            result.add(logVo);
            System.out.println(sourceAsString);

            // 获取 source 的Map结构
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            // 获取 message 的值
            System.out.println("--message--: " + sourceAsMap.get("message"));
        });
        System.out.println("-----:"+result);
    }
}
